﻿using Common.Extension;
using System.Text.RegularExpressions;

namespace DesignModeConsole.设计原则.DRYPrinciple
{
    /*
    DRY原则： 不要写重复代码

    三个典型代码重复：逻辑重复、功能语义重复、代码执行重复
     */

    /// <summary>
    /// 逻辑重复
    /// </summary>
    public class UserAuthenticator
    {
        //总结：尽管代码代码实现逻辑相同，但是语义不同，所以判定为不违反dry原则。如果要优化，
        //可以拆分更细粒度的函数来解决问题，比如将是否为null拆分等

        public bool Authenticate(string username, string password)
        {
            if (!IsValidUserName(username))
                throw new ArgumentNullException();
            if (!IsValidPassword(password))
                throw new ArgumentNullException();

            // 逻辑重复
            return true;
        }

        // IsValidUserName和IsValidPassword重复代码被写了两次

        private bool IsValidUserName(string userName)
        {
            if (userName.IsNullOrEmpty())
                return false;

            var length = userName.Length;
            if (length < 4 || length > 64)
                return false;

            return true;
        }

        private bool IsValidPassword(string userName)
        {
            if (userName.IsNullOrEmpty())
                return false;

            var length = userName.Length;
            if (length < 4 || length > 64)
                return false;

            return true;
        }

        /// <summary>
        /// 违反单一职责原则和接口隔离原则
        /// </summary>
        /// <param name="userNameOrPassword"></param>
        /// <returns></returns>
        private bool IsValidUserNameOrPassword(string userNameOrPassword)
        {
            if (userNameOrPassword.IsNullOrEmpty())
                return false;

            var length = userNameOrPassword.Length;
            if (length < 4 || length > 64)
                return false;

            return true;
        }
    }

    /// <summary>
    /// 功能语义重复
    /// </summary>
    public class UserService1
    {
        //总结：逻辑不重复、语义重复也就是功能重复，所以认为他违背了dry原则，应该同一个功能的方法在一个项目中只写一次。

        public bool isValidIp(string ipAddress)
        {
            if (ipAddress.IsNullOrEmpty()) return false;
            var regex = new Regex("^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."
            + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
            + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
            + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$");
            return regex.IsMatch(ipAddress);
        }

        public bool checkIfIpValid(string ipAddress)
        {
            if (ipAddress.IsNullOrEmpty()) return false;
            var ipUnits = ipAddress.Split(",");
            if (ipUnits.Length != 4)
            {
                return false;
            }
            for (var i = 0; i < 4; ++i)
            {
                int ipUnitIntValue;
                try
                {
                    ipUnitIntValue = int.Parse(ipUnits[i]);
                }
                catch
                {
                    return false;
                }
                if (ipUnitIntValue < 0 || ipUnitIntValue > 255)
                {
                    return false;
                }
                if (i == 0 && ipUnitIntValue == 0)
                {
                    return false;
                }
            }
            return true;
        }
    }

    /// <summary>
    /// 代码执行重复
    /// </summary>
    public class UserService2
    {
        //总结：email被校验了两次，所以这是执行重复

        public string Login(string email, string password)
        {
            var isExisted = CheckIfUserExisted(email, password);
            if (!isExisted)
                throw new ArgumentException();

            return "userinfo";
        }

        public bool CheckIfUserExisted(string email, string password)
        {
            if (!ValidEmail(email))
                throw new AggregateException();

            if (password.IsNullOrEmpty())
                throw new ArgumentException();

            return true;
        }

        public string GetUserByEamil(string email)
        {
            if (!ValidEmail(email))
                throw new AggregateException();

            return "userinfo";
        }

        private bool ValidEmail(string email)
        {
            return true;
        }
    }
}